package org.beetl.sql.core.mapper.internal;


import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.beetl.sql.clazz.kit.AutoSQLEnum;
import org.beetl.sql.core.SQLExecutor;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.engine.PageQuery;
import org.beetl.sql.core.range.RangeSql;
import org.beetl.sql.mapper.MapperInvoke;

public class TemplatePageAmi extends MapperInvoke{

	@Override
	public Object call(SQLManager sm, Class entityClass, Method m, Object[] args) {
		PageQuery query = (PageQuery)args[0];
		Object obj = query.getParas();
		long totalRow = 0;
		if(query.getTotalRow()<0){
			SQLExecutor script = sm.getScript(entityClass, AutoSQLEnum.SELECT_COUNT_BY_TEMPLATE);
			totalRow = script.singleSelect(Long.class, obj);
			query.setTotalRow(totalRow);
		}
		List<Object> list = null;
		if(totalRow==0) {
		    list = new ArrayList<>(0);
		}else {
		    long start = (sm.isOffsetStartZero() ? 0 : 1) + (query.getPageNumber() - 1) * query.getPageSize();
            long size = query.getPageSize();
            SQLExecutor script = sm.getScript(sm.getClass(), AutoSQLEnum.SELECT_BY_TEMPLATE);
            if(query.getOrderBy()!=null&&query.getOrderBy().trim().length()!=0) {
                list = template(sm, script, entityClass, script, start, size, query.getOrderBy());
            }else {
            	script.getExecuteContext().sqlSource.getTemplate();
                list=script.select(entityClass, args[0], ((Integer) args[1]).longValue(), ((Integer) args[2]).longValue());
            }
		}
		query.setList(list);
		return query;
	}

	/**
	 * 根据模板查询数据，支持分页和排序
	 *
	 * @param target 目标类型
	 * @param paras 参数
	 * @param start 分页开始位置，如果不需要分页则传入-1
	 * @param size 分页大小，如果不需要分页则传入-1
	 * @param orderBy 排序字段，如果不需要排序则传入null或空字符串
	 * @return 查询结果列表
	 */
	private <T> List<T> template(SQLManager sm,SQLExecutor script,Class<T> target, Object paras, long start, long size, String orderBy) {
        String sqlTemplate = script.getExecuteContext().sqlSource.getTemplate();
        if (orderBy != null && orderBy.trim().length() != 0) {
            if (sqlTemplate.indexOf(" order by ") == -1) {
                //参考 AbstractDBStyle.getSelectTemplate
                sqlTemplate = sqlTemplate + " order by " + orderBy;
            } else {
                sqlTemplate = sqlTemplate + "," + orderBy;
            }
        }
        boolean pageable = start != -1 && size != -1;
        RangeSql rangeSql=null;
        if (pageable) {
        	rangeSql=sm.getDbStyle().getRangeSql();
        	sqlTemplate=rangeSql.toTemplateRange(target, sqlTemplate);
        }

        Map<String, Object> param = null;
        if (paras instanceof Map) {
            param = (Map) paras;
        } else {
            param = new HashMap<>();
            param.put("_root", paras);
        }

        if (pageable) {
        	rangeSql.addTemplateRangeParas(param, start, size);
        }
        List<T> list = sm.execute(sqlTemplate, target, param);
        return list;

    }
	
}
